import {
  Observable, of, from, throwError,
  tap, map, catchError,
  delay, timeout,
} from 'rxjs'

/**
 * rxjs 是一个用来处理异步的包
 * Observable 可观察对象 是 rxjs 的核心 表示一组数据流 生产发送的值可以是同步也可以是异步
 * Observable 生产发送的值可以由 observer 观察者进行订阅
 * observer 是一个观察者 定义了回调函数 用于处理 Observable 生产发送的数据
 * 
 * 
 */
// const observable$ = new Observable(subscriber => {
//   subscriber.next(1) // 生产发送值
//   subscriber.next(2)
//   subscriber.next(3)
//   subscriber.complete() // 完成生产发送值
// })

// // 返回一个订阅者
// const subscription = observable$.subscribe({
//   next: (val) => console.log('next', val),
//   complete: () => console.log('complete'),
//   error: e => console.log('error', e)
// })


// 取消订阅情况
// const observable = new Observable(subscriber => {
//   let count = 0;
//   const intervalId = setInterval(() => {
//     subscriber.next(count++)
//   }, 1000)
//   return () => { // 取消订阅方法
//     clearInterval(intervalId)
//   }
// })

// // 获取订阅者
// const subscription = observable
//   .subscribe(value => { // 观察者
//     console.log(value)
//   })

// setTimeout(() => {
//   subscription.unsubscribe() // 通过订阅者的 unsubscribe 方法取消订阅
// }, 1000 * 5)



// 创建操作符
// of 会返回一个可观察对象并生产发送一系列值
// const observable$ = of(1, 2, 3)
// observable$
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e)
//   })


// 创建操作符 from
// from 会返回一个可观察对象并生产发送值 
// const observable$ = from([1, 2, 3]) // 传递一个数组 会依次生产发送数组中每个元素值
// observable$
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e)
//   })

// from 会返回一个可观察对象并生产发送值 
// const observable$ = from(Promise.resolve(123)) // 传递一个Promise实例 会把Promise中的值生产发送
// observable$
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e)
//   })

// from 会返回一个可观察对象并生产发送值 
// 嵌套 promise 外层promise会把获取内层promise的值 扁平化
// const observable$ = from(Promise.resolve(Promise.resolve(1)))
// observable$
//   .subscribe({
//     next: (val) => console.log('next', val), // 1
//     complete: () => console.log('complete'), // complete
//     error: e => console.log('error', e)
//   })

// from 会返回一个可观察对象
// 如果 from 传递的是一个可观察对象则会原样返回
// const observable1$ = of(1)
// const observable2$ = from(observable1$)
// console.log(observable1$ === observable2$) // true


// throwError 返回一个可观察对象 并且会抛出一个异常
// 工厂函数返回的错误信息会被可观察对象的 subscribe 的 error 回调函数中进行捕获处理
// const observable$ = throwError(() => new Error('error 出错了'))
// observable$
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e) // 'error' 错误对象
//   })
// console.log('程序没有退出 错误对象已经被捕获到了') // 程序没有退出 错误对象已经被捕获到了



// tap 管道操作符 用于对 Observable 可观察对象生产发送的值进行副作用操作 比如记录日志 它不会改变中的值
// of(1, 2, 3)
//   .pipe(tap({
//     next: (val) => console.log('tap next', val),
//     complete: () => console.log('tap complete'),
//     error: e => console.log('tap error', e)
//   }))
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e)
//   })


// map 管道操作符 用于对 Observable 可观察对象生产发送的值进行映射操作 
// of(1, 2, 3)
//   .pipe(map(x => x * 2))
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e)
//   })


// catchError管道操作符 用于捕获 Observable 可观察对象抛出的错误 并处理错误返回一个新的可观察对象
// throwError(() => new Error('error 出错了'))
//   .pipe(catchError(e => { // 捕获上游可观察对象抛出的错误
//     // 这里可以对错误进行处理 处理完毕后返回一个新的可观察对象作为下游可观察对象
//     return of(e.message) // 返回一个新的可观察对象 并生产发送一个错误消息给新可观察对象
//   }))
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e),
//   })


// delay 管道操作符 用于延迟 Observable 可观察对象生产发送的值的时间
// of('hello')
//   .pipe(delay(2000))
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e),
//   })


// timeout 管道操作符 用于设置 Observable 可观察对象生产发送的值的超时时间 超时后自动取消订阅
// of('hello')
//   .pipe(
//     delay(1000), // 上游可观察对象 延迟1秒生产发送值
//     timeout(2000), // 只会接收上游戏2秒内生成的值 超时后自动取消订阅
//   )
//   .subscribe({
//     next: (val) => console.log('next', val),
//     complete: () => console.log('complete'),
//     error: e => console.log('error', e),
//   })


